Skip to content

Conversation

@t2gran
Copy link
Member

@t2gran t2gran commented Aug 8, 2025

Summary

This PR introduces carpooling as a sandbox feature in OTP, enabling passengers to be matched with shared carpool trips and integrating carpooling into multi-modal journey planning.

Key capabilities:

  • Direct carpooling routing (door-to-door trips)
  • Optimal passenger insertion into multi-stop carpool routes
  • Real-time updates via SIRI-ET
  • Multi-phase filtering (capacity, time, distance, direction)
  • A* street routing with performance optimizations

Implementation approach:

  • Sandbox feature behind OTPFeature.CarPooling toggle
  • Comprehensive test coverage (189+ tests, 100% passing)

Context:
This POC enables pilot programs where carpooling services integrate with public transit. Development is expected to take at least one year as we refine the feature based on pilot feedback and work with SIRI standardization in parallel.


What's Included

Core Routing

  • Optimal insertion algorithm with A* routing
  • Multi-stop trip support with passenger delta tracking
  • Passenger delay constraint validation (protects existing passengers)
  • Multi-phase filtering to eliminate incompatible trips

Data Management

  • CarpoolTrip domain model
  • SIRI-ET real-time updates via SiriETCarpoolingUpdater

Performance Optimizations

  • Beeline heuristics for early rejection
  • Segment caching
  • Ordered filter chain for maximum early rejection

API Integration

  • GraphQL carpooling types (CarpoolLeg)
  • Transmodel schema integration

What's NOT Included (Future Work)

Not in this PR:

  • Access/egress routing (actively being developed)
  • Pickup/dropoff area restrictions
  • Seat reservation system
  • Driver/passenger preference matching (wheelchair, bike compatibility, etc.)
  • Fare integration
  • Scaling optimizations for large trip counts

Configuration

Enable feature:

// otp-config.json
{
  "otpFeatures": {
    "CarPooling": true
  }
}

Configure SIRI-ET updater:
// router-config.json
{
  "updaters": [
    {
      "type": "siri-et-carpooling-updater",
      "feedId": "carpool-provider",
      "url": "https://api.example.com/siri",
      "frequencySec": 30
    }
  ]
}

Issue

Part of #7012 (carpooling feature request)
Supersedes #6604 (original POC issue)


Unit tests

189+ carpooling-specific tests (100% passing)

Test infrastructure includes builders and mocks for fast, isolated testing without graph infrastructure.


Documentation

JavaDoc throughout codebase


Changelog

Added:

  • Carpooling sandbox feature with optimal insertion routing
  • SIRI-ET carpooling updater for real-time trip updates

Configuration:

  • OTPFeature.CarPooling toggle (disabled by default)
  • SIRI-ET carpooling updater

Bumping the serialization version id

N/A - Sandbox feature does not require serialization bump (carpool trips stored in-memory only, not in graph.obj).


Migration / Compatibility

No breaking changes - all functionality behind OTPFeature.CarPooling toggle (disabled by default).

@t2gran t2gran requested a review from a team as a code owner August 8, 2025 10:57
@t2gran t2gran added !New Feature A functional feature targeting the end user. +Sandbox This will be implemented as a Sandbox feature Entur Test This is currently being tested at Entur +Skip Changelog This is not a relevant change for a product owner since last release. labels Aug 8, 2025
@t2gran t2gran marked this pull request as draft August 8, 2025 10:58
@codecov
Copy link

codecov bot commented Aug 8, 2025

Codecov Report

❌ Patch coverage is 42.01077% with 646 lines in your changes missing coverage. Please review.
✅ Project coverage is 71.78%. Comparing base (e9e4dff) to head (408397a).
⚠️ Report is 4 commits behind head on dev-2.x.

Files with missing lines Patch % Lines
...nner/ext/carpooling/updater/CarpoolSiriMapper.java 0.00% 153 Missing ⚠️
...entripplanner/ext/carpooling/model/CarpoolLeg.java 0.00% 96 Missing ⚠️
...t/carpooling/service/DefaultCarpoolingService.java 0.00% 67 Missing ⚠️
...xt/carpooling/updater/SiriETCarpoolingUpdater.java 0.00% 50 Missing ⚠️
...lanner/ext/carpooling/model/CarpoolLegBuilder.java 0.00% 41 Missing ⚠️
...ntripplanner/ext/carpooling/model/CarpoolStop.java 25.92% 40 Missing ⚠️
...xt/carpooling/internal/CarpoolItineraryMapper.java 0.00% 37 Missing ⚠️
...config/updaters/SiriETCarpoolingUpdaterConfig.java 0.00% 34 Missing ⚠️
...anner/ext/carpooling/model/CarpoolTripBuilder.java 58.18% 22 Missing and 1 partial ⚠️
...er/ext/carpooling/routing/CarpoolStreetRouter.java 33.33% 20 Missing ⚠️
... and 18 more
Additional details and impacted files
@@              Coverage Diff              @@
##             dev-2.x    #6791      +/-   ##
=============================================
- Coverage      72.18%   71.78%   -0.41%     
- Complexity     19840    20007     +167     
=============================================
  Files           2155     2182      +27     
  Lines          80051    81158    +1107     
  Branches        8082     8197     +115     
=============================================
+ Hits           57786    58257     +471     
- Misses         19419    20039     +620     
- Partials        2846     2862      +16     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@t2gran t2gran added this to the 2.8 (next release) milestone Aug 11, 2025
@vpaturet vpaturet removed the Entur Test This is currently being tested at Entur label Aug 13, 2025
@eibakke eibakke added the Entur Test This is currently being tested at Entur label Aug 19, 2025
@t2gran t2gran removed the Entur Test This is currently being tested at Entur label Aug 19, 2025
@eibakke eibakke added Entur Test This is currently being tested at Entur and removed Entur Test This is currently being tested at Entur labels Aug 20, 2025
@optionsome optionsome changed the title Carpooling POK Carpooling POC Sep 2, 2025
@t2gran t2gran modified the milestones: 2.8, 2.9 (next release) Sep 10, 2025
@eibakke eibakke added the Entur Test This is currently being tested at Entur label Sep 11, 2025
@t2gran t2gran added Entur Test This is currently being tested at Entur and removed Entur Test This is currently being tested at Entur labels Sep 11, 2025
@t2gran t2gran removed the Entur Test This is currently being tested at Entur label Sep 22, 2025
Copy link
Member

@optionsome optionsome left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did a partial review so you can fix some things before I have time to review the rest

Comment on lines +17 to +18
* - More than {@code maxDelay} additional wait time at their pickup location
* - More than {@code maxDelay} later arrival at their dropoff location
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't waiting at the pickup location automatically mean later arrival to the dropoff location?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but you may experience a greater delay to your scheduled dropoff than your pickup, if say, there is a new pickup inserted before your pickup and a another one before your dropoff. So the delay at your pickup is t, but the delay at your dropoff may be t+t1.


// Passenger start time is max of request time and when driver arrives
var startTime = request.dateTime().isAfter(driverPickupTime.toInstant())
? request.dateTime().atZone(ZoneId.of("Europe/Oslo"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slightly weird hardcoded timezone. I think you could fetch the actual timezone from the transitservice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, agree. Will address.

Comment on lines +142 to +143
.withFrom(Place.normal(fromVertex, new NonLocalizedString("Carpool boarding")))
.withTo(Place.normal(toVertex, new NonLocalizedString("Carpool alighting")))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could translate these with internals.properties thingy, but that's up to you.

Comment on lines 43 to 45
* {@link org.opentripplanner.ext.carpooling.CarpoolingRepository}.
* {@link CarpoolingRepository}.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a comment about usage of a full path instead of importing a class in code, but for javadoc, you should use the full path instead of importing when the referenced class isn't imported for other reasons. You made the same change in some other places as well in the recent commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

!New Feature A functional feature targeting the end user. +Sandbox This will be implemented as a Sandbox feature +Skip Changelog This is not a relevant change for a product owner since last release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants